// 引入mongodb
const exp = require('constants');
let { MongoClient, ObjectId } = require('mongodb');

// 定义配置信息
let { MESSAGE } = require('./config')


// 定义Database类
class Database {
    // 在constructor中定义
    constructor(mongoClientUrl, dbName, collName) {
        this.mongoClientUrl = mongoClientUrl;
        this.dbName = dbName;
        this.collName = collName;
    }

    // 定义连接数据库的方法
    connect() {
        // 返回promise
        return new Promise((resolve, reject) => {
            if(this.db) {
                return resolve(this.db)
            }
            MongoClient.connect(this.mongoClientUrl, { useNewUrlParser: true }, (err, client) => {
                // 捕获异常
                if (err) {
                    return reject(MESSAGE.databaseClinetError);
                }
                this.db = client.db(this.dbName);
                // 监听关闭
                process.on('exit', () => {
                    client.close()
                })
                // this.client = client
                // 执行成功返回数据库
                // resolve(client.dbName(this.dbName));
                // 如果想要在每一次操作完毕之后 断开连接 连同client一起返回
                resolve(this.db)

            })
        })
    }

    // 修改集合的方法
    collection(collName) {
        // 修改集合名称
        this.collName = collName;
        // 为了链式调用 返回this
        return this;
    }

    // 插入一条数据方法
    insertOne(obj) {
        // 返回promise对象
        return new Promise((resolve, reject) => {
            // 连接数据
            this.connect()
                .then(
                    db => {
                        // 操作集合
                        db.collection(this.collName)
                            // 调用插入方法
                            .insertOne(obj, (err, { result }) => {
                                // 捕获异常
                                if (err) {
                                    reject(MESSAGE.databaseInsertError)
                                } else if (result.n > 0) {
                                    resolve(result);
                                } else {
                                    reject(MESSAGE.databaseInsertNotData);
                                }
                                // 断开连接
                                
                            })
                    }
                )
        })

    }

    // 插入多条数据
    insertMany(arr) {
        // 返回promise对象
        return new Promise((resolve, reject) => {
            // 连接数据库
            this.connect()
                .then(
                    db => {
                        // 操作集合
                        db.collection(this.collName)
                            .insertMany(arr, (err, { result }) => {
                                if (err) {
                                    reject(MESSAGE.databaseInsertError)
                                } else if (result.n > 0) {
                                    resolve(result);
                                } else {
                                    reject(MESSAGE.databaseInsertNotData);
                                }

                                // 中断连接
                                
                            })

                    }
                )
        })
    }

    // 删除一条数据方法
    deleteOne(obj) {
        // 返回promise对象
        return new Promise((resolve, reject) => {
            // 连接数据库
            this.connect()
                .then(
                    db => {
                        // 判断是否传递的是_id字段 
                        if (obj._id) {
                            obj._id = ObjectId(obj._id);
                        }

                        // 操作集合
                        db.collection(this.collName)
                            // 调用删除方法
                            .deleteOne(obj, (err, { result }) => {
                                // 捕获异常
                                if (err) {
                                    reject(MESSAGE.databaseDeleteError);
                                } else if (result.n > 0) {
                                    resolve(result);
                                } else {
                                    reject(MESSAGE.databaseDeleteNotData);
                                }
                                // 中断连接
                                
                            })
                    }
                )
        })
    }

    // 删除多条数据
    deleteMany(arr) {
        return Promise.all(arr.map(item => this.deleteOne(item)))
    }
    
    // 修改一条数据
    updateOne(query, newObj) {
        // 返回promise对象
        return new Promise((resolve, reject) => {
            // 建立连接
            this.connect()
                .then(
                    db => {
                        // 判断传递的query数据是否传递了_id
                        if (query._id) {
                            query._id = ObjectId(query._id);
                        }

                        // 操作集合
                        db.collection(this.collName)
                            .updateOne(query, { $set: newObj }, (err, { result }) => {
                                // 捕获异常
                                if (err) {
                                    reject(MESSAGE.databaseUpdateError)
                                } else if (result.n > 0) {
                                    resolve(result);
                                } else {
                                    reject(MESSAGE.databaseUpdateNotData);
                                }
                                // 中断连接
                                
                            })
                    }
                )
        })
        
    }

    // 修改多条数据
    updateMany(arr) {
        return Promise.all(arr.map(itemArr =>  this.updateOne(...itemArr)));
    }

    // 查找一条数据
    findOne(obj) {
        // 返回promise对象
        return new Promise((resolve, reject) => {
            // 连接数据
            this.connect()
                .then(
                    db => {
                        // 判断传递的query数据是否传递了_id
                        if (obj._id) {
                            obj._id = ObjectId(obj._id);
                        }

                        // 操作集合
                        db.collection(this.collName)
                            // 调用查找方法
                            .findOne(obj, (err, result) => {
                                // console.log(err, 111, result);
                                // 捕获错误
                                if (err) {
                                    reject(MESSAGE.databaseFindError);
                                } else if (result) {
                                    resolve(result);
                                } else {
                                    reject(MESSAGE.databaseFindNotData);
                                }
                                // 中断连接
                                
                            })
                           
                    }
                )
        })

    }

    // 查找多条数据
    // fn = data => data  function (data) { return data };
    findMany(obj, fn = data => data) {
        // 返回promise对象
        return new Promise((resolve, reject) => {
            // 连接数据
            this.connect()
                .then(
                    db => {
                        // 操作集合
                        var result = db.collection(this.collName).find(obj);
                            // 调用查找方法
                            // .find(obj)
                            // 执行fn
                            fn(result)
                            .toArray((err, arr) => {
                                // 捕获异常
                                if (err) {
                                    reject(MESSAGE.databaseFindError);
                                } else if (arr.length) {
                                    resolve(arr)
                                } else {
                                    reject(MESSAGE.databaseFindNotData);
                                }

                                // 中断连接
                                
                            })
                           
                    }
                )
        })

    }


}

// 暴露接口
module.exports = Database;